//
//  Chunk.m
//  FirstSCAnalyzer
//
//  Created by Roelant Ossewaarde on 9/4/09.
//  Copyright 2009 SUNY Buffalo. All rights reserved.
//

#import "Chunk.h"
#import "SCWorkoutDataBlock.h"


@implementation Chunk

@synthesize data;

-(id) initWithData:(NSData *) myData {
	if (self = [super init]) {
		[self setData:myData];
		return self;
	}
}

-(ChunkType) typeOfChunk {
	unsigned char buf[100];
	BOOL blockIsNotNull = NO;
	NSRange range;
	range.location = 0;
	range.length = 16;
	[[self data] getBytes:&buf range:range];
	for (int i=0; i<16; i++) {
		if (buf[i] != 0x0) {
			blockIsNotNull = YES;
			break;
		}
	}
	if (blockIsNotNull == NO) return NullChunkType;
	if (buf[14] == 0xa5 && buf[15] == 0xa5) return DateAndTimeChunkType;
	if (buf[7] == 0 && buf[14] == 0 && buf[15] == 0 && (buf[0] == 0 || buf[0] == 1 || buf[0] == 2)) return AutomemWorkoutChunkType;
	return UnknownChunkType;
}

-(IntervalType) getIntervalType {
	unsigned char buf[20];
	[data getBytes:buf];
	switch (buf[0]) {
		case 0 : return DistanceIntervalType; break;
		case 1 : return TimeIntervalType; break;
		case 2 : return StrokeIntervalType; break;
		default : return UnknownIntervalType; break;
	}
}

-(long) getTime {
	unsigned char buf[20];
	long num = 0;
	[data getBytes:buf];
	num = (buf[1] << 16) | (buf[2] << 8) | buf[3];
	return num;
	return num;
}

-(long) getDistance {
	unsigned char buf[20];
	long num = 0;
	[data getBytes:buf];
	num = (buf[4] << 16) | (buf[5] << 8) | buf[6];
	return num;
}

-(long) getAverageStrokeRate {
	unsigned char buf[20];
	long num = 0;
	[data getBytes:buf];
	num = (buf[8] << 8) | buf[9];
	return num;
}

-(long) getNumberOfStrokes {
	unsigned char buf[20];
	long num = 0;
	[data getBytes:buf];
	num = (buf[10] << 8) | buf[11];
	return num;
}

-(long) getHeartRate {
	unsigned char buf[20];
	long num = 0;
	[data getBytes:buf];
	num = (buf[12] << 8) | buf[13];
	return num;
}

-(int) getYear {
	NSRange range;
	range.location = 0;
	range.length = 2;
	return [self decodeBCD:[data subdataWithRange:range]];
}


-(int) getDay {
	NSRange range;
	range.location = 3;
	range.length = 1;
	return [self decodeBCD:[data subdataWithRange:range]];
}

-(int) getHours {
	NSRange range;
	range.location = 4;
	range.length = 1;
	return [self decodeBCD:[data subdataWithRange:range]];
}

-(int) getMinutes {
	NSRange range;
	range.location = 5;
	range.length = 1;
	return [self decodeBCD:[data subdataWithRange:range]];
}

-(int) getSeconds {
	NSRange range;
	range.location = 6;
	range.length = 1;
	return [self decodeBCD:[data subdataWithRange:range]];
}

-(int) getMonth {
	unsigned char buf[20];
	[data getBytes:buf];
	return buf[2];
}

-(void)logChunk {
	char spacer[10] = "   ";
	if ([self typeOfChunk] == DateAndTimeChunkType) {
		NSLog(@"chunk is a date&time chunk");
		NSLog(@"%sdate:         %i/%i/%i %i:%i.%i", spacer, [self getMonth], [self getDay], [self getYear], [self getHours], [self getMinutes], [self getSeconds]);
	} else if  ([self typeOfChunk] == AutomemWorkoutChunkType) {
		NSLog(@"chunk is a workout chunk");
		if ([self getTime] != 0) {
			switch ([self getIntervalType]) {
				case DistanceIntervalType: NSLog(@"%sintervaltype: distance", spacer); break;
				case TimeIntervalType:     NSLog(@"%sintervaltype: time", spacer); break;
				case StrokeIntervalType:   NSLog(@"%sintervaltype: stroke", spacer); break;
			}
			NSLog(@"%stime:         %ld", spacer, [self getTime]/64);
			NSLog(@"%sdistance:     %ld", spacer, [self getDistance]/16);
			NSLog(@"%savg strkate:  %ld.%2i", spacer, [self getAverageStrokeRate]/256,[self getAverageStrokeRate] % 256 );
			NSLog(@"%s# strokes:    %ld", spacer, [self getNumberOfStrokes]);
			
		}
	} else if  ([self typeOfChunk] == NullChunkType) {
		NSLog(@"chunk is a NULL chunk");

	} else {
		NSLog(@"Failed to recognize chunk, dump of bytes:");
		char buf[20];
		NSRange range;
		range.location = 0;
		range.length = 16;
		[[self data] getBytes:&buf range:range];
		for (int i=0; i<15; i++) {
			NSLog(@"byte [%i]: %X %c", i, buf[i], buf[i]);
		}
			
	}
}

-(NSDate *) dateValue {
	if ([self typeOfChunk] != DateAndTimeChunkType) return nil;
	NSDateComponents *components = [[NSDateComponents alloc] init];
	[components setDay:[self getDay]];
	[components setMonth:1+[self getMonth]];
	[components setYear:[self getYear]];
	[components setHour:[self getHours]];
	[components setMinute:[self getMinutes]];
	[components setSecond:[self getSeconds]];
	NSCalendar *gregorian = [[NSCalendar alloc]
							 initWithCalendarIdentifier:NSGregorianCalendar];
	NSDate *date = [gregorian dateFromComponents:components];
	[components release];
	[gregorian release];
//	NSLog(@"datevalue computed to: %@", [date description]);
	return date;
}

-(int)decodeBCD:(NSData*)bcdInt {
	int i;
	char buf[10];
	int final = 0;
	
	[bcdInt getBytes:buf];
	for (i = 0; i < [bcdInt length]; i++) {
		//int msb = [bcdInt bytes][i] & 0xF0h;
		int msb = 10 * (buf[i] & 0xF0h)>>4;
		int lsb = buf[i] & 0x0Fh;
		final *= 100;
		final += msb + lsb;
		//		int lsb = 
		//		NSLog(@"MSB: %i LSB: %i final: %i", msb, lsb, final);
	}
	return final;
}

@end
